﻿#include"Thread_pool.h"
#include<iostream>

Thread_pool::Thread_pool(int min, int max):m_minthread(min),m_maxthread(max),
m_stop(false),m_idlethread(min),m_curthread(min),m_exithread(0)
{
	//创建管理者线程
	m_manager = new thread(&Thread_pool::manager,this);
	//创建工作的线程
	for (int i = 0; i < m_curthread; i++)
	{
		thread t(&Thread_pool::worker, this);
		m_workers.insert(make_pair(t.get_id(),move(t)));
	}
}

Thread_pool::~Thread_pool()
{
	m_stop = true;
	m_condition.notify_all();
	for (auto& it : m_workers)
	{
		thread& t = it.second;
		if (t.joinable())
		{
			cout << "********* 线程 ID：" << t.get_id() <<" 将要退出了 ..." << endl;
			t.join();
		}
	}
	if (m_manager->joinable())
	{
		m_manager->join();
	}
	delete m_manager;
}

//添加任务(生产者生产)
void Thread_pool::add_task(function<void(void)> task)
{
	{
		lock_guard<mutex>locker(m_queue_mutex);
		m_tasks.emplace(task);
	}
	m_condition.notify_one();
}

//管理者线程
void Thread_pool::manager(void)
{
	while (!m_stop.load())
	{
		this_thread::sleep_for(chrono::seconds(2));
		int idel = m_idlethread.load();
		int cur = m_curthread.load();
		if (!m_stop.load()&& idel > cur / 2 && cur > m_minthread)
		{
			m_exithread.store(2);
			m_condition.notify_all();
			unique_lock<mutex>lck(m_ids_mutex);
			for (auto& id : m_ids)
			{
				auto it = m_workers.find(id);
				if (it != m_workers.end())
				{
					cout << "========= 线程 ID：" << (*it).first << "被销毁了 ..." << endl;
					(*it).second.join();
					m_workers.erase(it);
				}
			}
			m_ids.clear();
		}
		else if (idel == 0 && cur < m_maxthread)
		{
			thread t(&Thread_pool::worker, this);
			m_workers.insert(make_pair(t.get_id(), move(t)));
			m_curthread++;
			m_idlethread++;
		}
	}
}

//任务函数(消费者消费)
void Thread_pool::worker(void)
{
	while (!m_stop.load())
	{
		function<void(void)>task = nullptr;
		{
			unique_lock<mutex>locker(m_queue_mutex);
			while (m_tasks.empty() && !m_stop)
			{
				m_condition.wait(locker);
				if (m_exithread.load() > 0)
				{
					m_curthread--;
					m_idlethread--;
					m_exithread--;
					cout << "-------------- 线程退出了，ID：" << this_thread::get_id() << endl;
					unique_lock<mutex>lck(m_ids_mutex);
					m_ids.emplace_back(this_thread::get_id());
					return;
				}
			}
			if (!m_tasks.empty())
			{
				cout << "取出了一个任务..." << endl;
				task = move(m_tasks.front());
				m_tasks.pop();
			}
		}
		if (task)
		{
			m_idlethread--;
			task();
			m_idlethread++;
		}
	}
}
